package slice

import (
	"errors"
	"fmt"
	"sort"
	"sync"
)

type MaxStepSlice []*MaxStepItem

func NewMaxStepSlice() *MaxStepSlice {
	return &MaxStepSlice{}
}

func (s *MaxStepSlice) Add(item *MaxStepItem) {
	*s = append(*s, item)
}

func (s *MaxStepSlice) ChooseItem() (*MaxStepItem, error) {
	if len(*s) == 0 {
		return nil, errors.New("slice is empty")
	}
	sort.Slice(*s, func(i, j int) bool {
		return (*s)[i].SortNumber < (*s)[j].SortNumber
	})
	value := (*s)[0]
	value.countIncrease()
	return value, nil
}
func (s *MaxStepSlice) ForEach(callback func(*MaxStepItem)) {
	for _, item := range *s {
		callback(item)
	}
}

type MaxStepItem struct {
	Name       string `json:"name"`
	Value      string `json:"value"`
	Count      int    `json:"count"`
	MaxCount   int    `json:"max_count"`
	MaxStep    int    `json:"max_step"`
	SortNumber int    `json:"sort_number"`
	lock       sync.Mutex
}

func NewMaxStepItemWithStep(name string, value string, maxCount, MaxStep int) *MaxStepItem {
	return &MaxStepItem{
		Name:       name,
		Value:      value,
		Count:      0,
		MaxCount:   maxCount,
		MaxStep:    MaxStep,
		SortNumber: 0,
	}
}
func NewMaxStepItem(name string, value string, maxCount int) *MaxStepItem {
	return &MaxStepItem{
		Name:       name,
		Value:      value,
		Count:      0,
		MaxCount:   maxCount,
		MaxStep:    1,
		SortNumber: 0,
	}
}

func (i *MaxStepItem) countIncrease() {
	step := 1
	if i.Count > i.MaxCount && i.MaxStep != 1 {
		step = i.MaxStep
	}
	i.lock.Lock()
	i.Count += 1
	i.SortNumber += step
	i.lock.Unlock()
}

func (i *MaxStepItem) Info() string {
	return fmt.Sprintf("%s: %s (count: %d,maxCount: %d,maxStep: %d, sort_number: %d)", i.Name, i.Value, i.Count, i.MaxCount, i.MaxStep, i.SortNumber)
}
